package com.leadcloud.nim.login;

import android.Manifest;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.ViewTreeObserver;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.Toast;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.leadcloud.nim.CommonCache;
import com.netease.nim.uikit.common.MyConst;
import com.leadcloud.nim.R;
import com.leadcloud.nim.config.preference.Preferences;
import com.leadcloud.nim.config.preference.UserPreferences;
import com.leadcloud.nim.main.activity.MainActivity;
import com.netease.nim.uikit.api.NimUIKit;
import com.netease.nim.uikit.common.activity.UI;
import com.netease.nim.uikit.common.http.NimHttpClient;
import com.netease.nim.uikit.common.ui.dialog.DialogMaker;
import com.netease.nim.uikit.common.ui.dialog.EasyAlertDialogHelper;
import com.netease.nim.uikit.common.ui.widget.ClearableEditTextWithIcon;
import com.netease.nim.uikit.common.util.log.LogUtil;
import com.netease.nim.uikit.common.util.string.MD5;
import com.netease.nim.uikit.support.permission.MPermission;
import com.netease.nim.uikit.support.permission.annotation.OnMPermissionDenied;
import com.netease.nim.uikit.support.permission.annotation.OnMPermissionGranted;
import com.netease.nim.uikit.support.permission.annotation.OnMPermissionNeverAskAgain;
import com.netease.nimlib.sdk.AbortableFuture;
import com.netease.nimlib.sdk.NIMClient;
import com.netease.nimlib.sdk.RequestCallback;
import com.netease.nimlib.sdk.StatusBarNotificationConfig;
import com.netease.nimlib.sdk.auth.AuthService;
import com.netease.nimlib.sdk.auth.ClientType;
import com.netease.nimlib.sdk.auth.LoginInfo;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录界面
 */
public class LoginActivity extends UI implements OnKeyListener {

    private static final String TAG = LoginActivity.class.getSimpleName();
    private static final String KICK_OUT = "KICK_OUT";
    private final int BASIC_PERMISSION_REQUEST_CODE = 110;

    //private TextView rightTopBtn;  // ActionBar完成按钮

    private ClearableEditTextWithIcon loginAccountEdit;
    private ClearableEditTextWithIcon loginPasswordEdit;
    private TextView loginBtn;



    private AbortableFuture<LoginInfo> loginRequest;
    private CheckBox cb_rem_pwd;
    private TextView tv_login_error;

    public static void start(Context context) {
        start(context, false);
    }

    public static void start(Context context, boolean kickOut) {
        Intent intent = new Intent(context, LoginActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.putExtra(KICK_OUT, kickOut);
        context.startActivity(intent);
    }

    @Override
    protected boolean displayHomeAsUpEnabled() {
        return false;
    }

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        return false;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login_activity);
        requestBasicPermission();
        onParseIntent();
        setupLoginPanel();
    }

    /**
     * 基本权限管理
     */

    private final String[] BASIC_PERMISSIONS = new String[]{
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE
    };

    private void requestBasicPermission() {
        MPermission.with(LoginActivity.this)
                .setRequestCode(BASIC_PERMISSION_REQUEST_CODE)
                .permissions(BASIC_PERMISSIONS)
                .request();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        MPermission.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
    }

    @OnMPermissionGranted(BASIC_PERMISSION_REQUEST_CODE)
    public void onBasicPermissionSuccess() {
        //Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show();
        NimHttpClient.getInstance().init(CommonCache.getContext());
    }

    @OnMPermissionDenied(BASIC_PERMISSION_REQUEST_CODE)
    @OnMPermissionNeverAskAgain(BASIC_PERMISSION_REQUEST_CODE)
    public void onBasicPermissionFailed() {
        Toast.makeText(this, "授权失败", Toast.LENGTH_SHORT).show();
    }

    private void onParseIntent() {
        if (getIntent().getBooleanExtra(KICK_OUT, false)) {
            int type = NIMClient.getService(AuthService.class).getKickedClientType();
            String client;
            switch (type) {
                case ClientType.Web:
                    client = "网页端";
                    break;
                case ClientType.Windows:
                case ClientType.MAC:
                    client = "电脑端";
                    break;
                case ClientType.REST:
                    client = "服务端";
                    break;
                default:
                    client = "移动端";
                    break;
            }
            EasyAlertDialogHelper.showOneButtonDiolag(LoginActivity.this, getString(R.string.kickout_notify),
                    String.format(getString(R.string.kickout_content), client), getString(R.string.ok), true, null);
        }
    }

    /**
     * addLayoutListener方法如下
     * @param main 根布局
     * @param scroll 需要显示的最下方View
     */
    public void addLayoutListener(final View main, final View scroll) {
        main.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect rect = new Rect();
                //1、获取main在窗体的可视区域
                main.getWindowVisibleDisplayFrame(rect);
                //2、获取main在窗体的不可视区域高度，在键盘没有弹起时，main.getRootView().getHeight()调节度应该和rect.bottom高度一样
                int mainInvisibleHeight = main.getRootView().getHeight() - rect.bottom;
                int screenHeight = main.getRootView().getHeight();//屏幕高度
                //3、不可见区域大于屏幕本身高度的1/4：说明键盘弹起了
                if (mainInvisibleHeight > screenHeight / 4) {
                    int[] location = new int[2];
                    scroll.getLocationInWindow(location);
                    // 4､获取Scroll的窗体坐标，算出main需要滚动的高度
                    int srollHeight = (location[1] + scroll.getHeight()) - rect.bottom;
                    //5､让界面整体上移键盘的高度
                    main.scrollBy(0, srollHeight);
                } else {
                    //3、不可见区域小于屏幕高度1/4时,说明键盘隐藏了，把界面下移，移回到原有高度
                    main.scrollTo(0, 0);
                }
            }
        });
    }



    /**
     * 登录面板
     */
    private void setupLoginPanel() {
        loginAccountEdit = findView(R.id.edit_login_account);
        loginPasswordEdit = findView(R.id.edit_login_password);
        loginBtn = findView(R.id.login_btn);
        cb_rem_pwd = findView(R.id.cb_rem_pwd);
        tv_login_error = findView(R.id.tv_login_error);


        loginAccountEdit.setDeleteImage(R.mipmap.login_close);
        loginPasswordEdit.setDeleteImage(R.mipmap.login_hide,R.mipmap.login_reveal);

        loginAccountEdit.setIconResource(R.mipmap.login_account);
        loginPasswordEdit.setIconResource(R.mipmap.login_password);

        loginAccountEdit.setFilters(new InputFilter[]{new InputFilter.LengthFilter(32)});
        loginPasswordEdit.setFilters(new InputFilter[]{new InputFilter.LengthFilter(32)});
        loginAccountEdit.addTextChangedListener(textWatcher);
        loginPasswordEdit.addTextChangedListener(textWatcher);
        loginPasswordEdit.setOnKeyListener(this);

        String userName = Preferences.getUserName();
        loginAccountEdit.setText(userName);
        String pwd = Preferences.getPwd();
        loginPasswordEdit.setText(pwd);
        loginBtn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                loginToMyServer();
            }
        });

        cb_rem_pwd.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                Preferences.saveRemenberPwd(b);
            }
        });
        if(Preferences.isRemenberPwd()){
            cb_rem_pwd.setChecked(true);
        }
        addLayoutListener(findView(R.id.sv_wrapper),loginBtn);
    }


    private TextWatcher textWatcher = new TextWatcher() {

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable s) {
            boolean isEnable = loginAccountEdit.getText().length() > 0
                    && loginPasswordEdit.getText().length() > 0;
            updateLoginBtn(loginBtn, isEnable);
        }
    };

    private void updateLoginBtn(TextView btn, boolean isEnable) {
        btn.setEnabled(isEnable);
    }

    /**
     * ***************************************** 登录 **************************************
     */


    private void loginToMyServer() {
        DialogMaker.showProgressDialog(this, null, getString(R.string.logining), true, new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                if (loginRequest != null) {
                    loginRequest.abort();
                    onLoginDone();
                }
            }
        }).setCanceledOnTouchOutside(false);

        Map<String, String> headers = new HashMap<>(1);
        final String userName = loginAccountEdit.getEditableText().toString();
        final String password = loginPasswordEdit.getEditableText().toString();

        headers.put("Content-Type","application/x-www-form-urlencoded");
        String body = null;
        try {
            body = "userName" + "=" + URLEncoder.encode(userName, "UTF-8") + "&" +
                    "password" + "=" + URLEncoder.encode(password, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            body = "userName" + "=" + userName+ "&" +
                    "password" + "=" + password;
        }

        NimHttpClient.getInstance().execute(MyConst.LOGIN_URL, headers, body, true, new NimHttpClient.NimHttpCallback() {

            @Override
            public void onResponse(String response, int code, Throwable exception) {
                if (code != 200 || exception != null) {
                    if(exception != null){
                        LogUtil.e(TAG, "login failed : code = " + code + ", errorMsg = "+ exception.getMessage());
                    }
                    showErrorMsg("网络或服务器不可用");
                    onLoginDone();
                }else{
                    try {
                        JSONObject resObj = JSONObject.parseObject(response);
                        int resCode = resObj.getIntValue("code");
                        if (resCode == 1) {
                            resObj = resObj.getJSONObject("data");
                            final String account = resObj.getString("accId");
                            final String token = resObj.getString("token");
                            String userId = String.valueOf(resObj.getIntValue("userId"));
                            String orgId = resObj.getString("orgId");
                            String userType=resObj.getString("userType");
                            saveUserInfo(userId, orgId,userName,password,userType);
                            saveLoginInfo(resObj.toJSONString());
                            loginToNim(account, token);
                        } else if(resCode==0) {
                            onLoginDone();
                            showErrorMsg("用户名或密码错误");
                        } else {
                            onLoginDone();
                            showErrorMsg("出现未知异常，请重试");
                        }
                    } catch (Exception e) {
                        onLoginDone();
                        showErrorMsg("网络连接不正常");
                    }
                }
            }
        });
    }

    private void showErrorMsg(String s) {
        if(tv_login_error!=null){
            tv_login_error.setText(s);
            tv_login_error.setVisibility(View.VISIBLE);
        }
    }

    private void hideErrorMsg(){
        if(tv_login_error!=null){
            tv_login_error.setVisibility(View.GONE);
        }
    }

    private void loginToNim(final String account, final String token) {
        // 登录
        loginRequest = NimUIKit.login(new LoginInfo(account, token), new RequestCallback<LoginInfo>() {
            @Override
            public void onSuccess(LoginInfo param) {
                LogUtil.i(TAG, "login success");
                hideErrorMsg();
                onLoginDone();
                CommonCache.setAccount(account);
                saveLoginInfo(account, token);
                // 初始化消息提醒配置
                initNotificationConfig();
                WsManager.getInstance().init();
                // 进入主界面
                MainActivity.start(LoginActivity.this, null);
                finish();
            }

            @Override
            public void onFailed(int code) {
                onLoginDone();
                if (code == 302 || code == 404) {
                    showErrorMsg(getResources().getString(R.string.login_failed));
                } else {
                    showErrorMsg(getResources().getString(R.string.login_failed_net));
                }
                if(loginRequest!=null){
                    loginRequest.abort();loginRequest=null;
                }
            }

            @Override
            public void onException(Throwable exception) {
                showErrorMsg(getResources().getString(R.string.login_exception));
                onLoginDone();
                if(loginRequest!=null){
                    loginRequest.abort();loginRequest=null;
                }
            }
        });
    }


    private void initNotificationConfig() {
        // 初始化消息提醒
        NIMClient.toggleNotification(UserPreferences.getNotificationToggle());

        // 加载状态栏配置
        StatusBarNotificationConfig statusBarNotificationConfig = UserPreferences.getStatusConfig();
        if (statusBarNotificationConfig == null) {
            statusBarNotificationConfig = CommonCache.getNotificationConfig();
            UserPreferences.setStatusConfig(statusBarNotificationConfig);
        }
        // 更新配置
        NIMClient.updateStatusBarNotificationConfig(statusBarNotificationConfig);
    }

    private void onLoginDone() {
        loginRequest = null;
        DialogMaker.dismissProgressDialog();
    }

    private void saveLoginInfo(final String account, final String token) {
        Preferences.saveUserAccount(account);
        Preferences.saveUserToken(token);
    }

    private void saveUserInfo(final String userId, final String orgId, String userName, String password, String userType) {
        Preferences.saveUserId(userId);
        Preferences.saveOrgId(orgId);
        Preferences.saveUserName(userName);
        Preferences.saveUserType(userType);
        if(Preferences.isRemenberPwd()) {
            Preferences.savePwd(password);
        }
    }

    private void saveLoginInfo(String loginInfo) {
        Preferences.saveString("loginInfo",loginInfo);
    }

    //DEMO中使用 username 作为 NIM 的account ，md5(password) 作为 token
    //开发者需要根据自己的实际情况配置自身用户系统和 NIM 用户系统的关系
    private String tokenFromPassword(String password) {
        String appKey = readAppKey(this);
        boolean isDemo = "45c6af3c98409b18a84451215d0bdd6e".equals(appKey)
                || "fe416640c8e8a72734219e1847ad2547".equals(appKey);

        return isDemo ? MD5.getStringMD5(password) : password;
    }

    private static String readAppKey(Context context) {
        try {
            ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
            if (appInfo != null) {
                return appInfo.metaData.getString("com.netease.nim.appKey");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public boolean isTransStatusBar() {
        return true;
    }
}
